package com.smdp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smdp.dto.Result;
import com.smdp.dto.UserDTO;
import com.smdp.entity.Shop;
import com.smdp.entity.Voucher;
import com.smdp.mapper.VoucherMapper;
import com.smdp.entity.SeckillVoucher;
import com.smdp.service.ISeckillVoucherService;
import com.smdp.service.IShopService;
import com.smdp.service.IVoucherScheduleService;
import com.smdp.service.IVoucherService;
import com.smdp.utils.BloomFilterUtil;
import com.smdp.utils.UserHolder;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

import static com.smdp.utils.RedisConstants.SECKILL_STOCK_KEY;

/**
 * 优惠券服务实现类。
 * 包含商家新增优惠券、商家新增秒杀券、用户查询商家优惠券信息。新增秒杀券时，除了保存普通优惠券信息，还将秒杀券信息保存到数据库，
 * 将秒杀券库存信息保存到Redis，将秒杀券id保存到布隆过滤器，并通过RabbitMQ添加优惠券提醒任务。
 *
 * @author 蔡方珩
 */
@Service
public class VoucherServiceImpl extends ServiceImpl<VoucherMapper, Voucher> implements IVoucherService {

    @Resource
    private ISeckillVoucherService seckillVoucherService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private IVoucherScheduleService voucherScheduleService;

    @Resource
    private IShopService shopService;

    /**
     * 查询店铺的优惠券列表
     * @param shopId 店铺id
     * @return 优惠券列表
     */
    @Override
    public Result queryVoucherOfShop(Long shopId) {
        // 布隆过滤器
        boolean contains = BloomFilterUtil.shopBloomFilter.contains(shopId);
        if (!contains){
            // 1.不存在，返回空
            return Result.fail("店铺不存在！");
        }
        // 查询优惠券信息
        List<Voucher> vouchers = getBaseMapper().queryVoucherOfShop(shopId);
        // 返回结果
        return Result.ok(vouchers);
    }

    /**
     * 新增秒杀券。
     * 验证店主身份，如果是店主则新增秒杀券。除了保存普通优惠券信息，将秒杀券信息保存到数据库，将秒杀券库存信息保存到Redis，
     * 将秒杀券id保存到布隆过滤器，通过RabbitMQ添加优惠券提醒任务。
     * @param voucher 优惠券信息
     * @return 成功：优惠券id / 失败：失败原因
     */
    @Override
    @Transactional
    public Result addSeckillVoucher(Voucher voucher) {
        Long shopId = voucher.getShopId();
        Shop shop = shopService.getById(shopId);
        // 检查是否是店主
        Long ownerId = shop.getOwnerId();
        UserDTO user = UserHolder.getUser();
        if (!user.getId().equals(ownerId)){
            return Result.fail("只有店主可以添加优惠券！");
        }
        // 保存优惠券
        save(voucher);
        // 保存秒杀信息
        SeckillVoucher seckillVoucher = new SeckillVoucher();
        seckillVoucher.setVoucherId(voucher.getId());
        seckillVoucher.setStock(voucher.getStock());
        seckillVoucher.setBeginTime(voucher.getBeginTime());
        seckillVoucher.setEndTime(voucher.getEndTime());
        seckillVoucherService.save(seckillVoucher);
        // 保存秒杀库存到Redis中
        stringRedisTemplate.opsForValue().set(SECKILL_STOCK_KEY + voucher.getId(), voucher.getStock().toString());
        // 添加秒杀券提醒任务
        voucherScheduleService.addVoucherSchedule(voucher);
        // 将信息保存到布隆过滤器
        BloomFilterUtil.seckillBloomFilter.add(voucher.getId());
        return Result.ok(voucher.getId());
    }

    /**
     * 新增普通券。
     * 验证店主身份，如果是店主则新增优惠券。
     * @param voucher 优惠券信息
     * @return 成功：优惠券id / 失败：失败原因
     */
    @Override
    public Result addVoucher(Voucher voucher) {
        Long shopId = voucher.getShopId();
        Shop shop = shopService.getById(shopId);
        // 检查是否是店主
        Long ownerId = shop.getOwnerId();
        UserDTO user = UserHolder.getUser();
        if (!user.getId().equals(ownerId)){
            return Result.fail("只有店主可以更新店铺！");
        }
        // 添加优惠券
        boolean isSuccess = save(voucher);
        if (!isSuccess){
            return Result.fail("添加失败");
        }
        BloomFilterUtil.voucherBloomFilter.add(voucher.getId());
        return Result.ok(voucher.getId());
    }
}
